#include "Parser.h"

bool Parser::isLeftParanthesis(char character)
{
	return character == '(';
}

bool Parser::isRightParanthesis(char character)
{
	return character == ')';
}

bool Parser::isOperator(char character)
{
	switch(character)
    {
		case '+' : return true;
        case '*' : return true;                                            
        case '|' : return true;
		case '.' : return true;
        case ' ' : return true;
        default  : return false;
    }
}

bool Parser::isInput(char character)
{
	return(!(isOperator(character) || isLeftParanthesis(character) || isRightParanthesis(character)));
}

int Parser::presedence(char ch)
{
	switch(ch)
    {
		case '*' : return 4;
        case '+' : return 4;
		case '.' : return 3;
        case ' ' : return 2;
		case '|' : return 1;
        default  : return 0;
    }
}

string Parser::expandRegexp(const string& expression)
{
	string withoutWhiteSpace;
	for(unsigned int i = 0; i < expression.length(); i++) 
	{
		char ch = expression.at(i);
		if (ch > 32) 
		{
			withoutWhiteSpace += ch;
		}
	}
	
	string result;
	for(unsigned int i=0; i< (withoutWhiteSpace.length()-1); i++)
	{
		char left = withoutWhiteSpace.at(i);
		char right = withoutWhiteSpace.at(i+1);
		result += left;
		if((isInput(left)) || (isRightParanthesis(left)) || left == '*' || left == '+') 
		{
			if((isInput(right)) || (isLeftParanthesis(right))) 
			{
				result += ' ';
			}
		}
	}
	result += withoutWhiteSpace[withoutWhiteSpace.length()-1];
	return result;
}

string Parser::toPostFix(string expression) {
	stack<char> chars;
	chars.push('(');
	expression += ')';

	string postfix;

	for (unsigned int i = 0; i < expression.length(); i++) {
		char token = expression[i];
		if (isLeftParanthesis(token)) 
		{
			chars.push(token);
		} 
		else if (isRightParanthesis(token)) 
		{
			char character = chars.top();
			chars.pop();
			while(!isLeftParanthesis(character)) 
			{
				postfix += character;
				character = chars.top();
				chars.pop();
			}
		} else if (isOperator(token))
		{
			while(presedence(chars.top()) >= presedence(token)) 	
			{
				postfix += chars.top();
				chars.pop();
			}
			chars.push(token);
		} 
		else 
		{
			postfix += token;
		}
 	}
	return postfix;
}

Regexp* Parser::toRegexp(const string& regexp) {
	string expanded = expandRegexp(regexp);

	string postfix = toPostFix(expanded);
	//postfix += " ";	
	stack<Regexp*> regexps;
	for (unsigned int i = 0; i < postfix.length(); i++) 
	{
		char token = postfix[i];
		if (isInput(token)) 
		{
			string s;
			s += token;
			Regexp* regExp = new Regexp(s);
			regexps.push(regExp);
		} 
		else {
			Regexp* regExp;
			if (token == '+' || token == '*') 
			{
				Regexp* operand = regexps.top();
				regexps.pop();
				if (token == '+') 
				{
					regExp = operand->plus();
				} 
				else 
				{
					regExp = operand->star();
				}
			} 
			else 
			{
				Regexp* operand2 = regexps.top();
				regexps.pop();
				Regexp* operand1 = regexps.top();
				regexps.pop();
				if (token == '|') 
				{
					regExp = operand1->or(operand2);
				} 
				else 
				{
					regExp = operand1->dot(operand2);
				}
			}
			regexps.push(regExp);
		}
	}
	Regexp* result = regexps.top();
	return result;
}

